package com.jili.helloword.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.InetSocketAddress;

/**
 * @author: Jili
 * @date: Created on 2022/4/22 15:52
 * 服务器端启动类
 */
public class AppServerHello {

    /** netty的Reactor线程池，初始化一个NioEventLoop数组，用来处理I/O
     * boss 线程组用于处理连接工作
     */
    private EventLoopGroup boss = new NioEventLoopGroup();
    /**
     * work 线程组用于数据处理
     */
    private EventLoopGroup work = new NioEventLoopGroup();

    private int port;

    public AppServerHello(int port){
        this.port=port;
    }
    public void run() throws Exception{
        try{
            //启动NIO服务
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(boss)
                    //通过工厂方法设计模式实例化channel
                    .channel(NioServerSocketChannel.class)
                    //设置端口
                    .localAddress(new InetSocketAddress(port))
                    //服务端可连接队列数,对应TCP/IP协议listen函数中backlog参数
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //设置TCP长连接,一般如果两个小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    //将小的数据包包装成更大的帧进行传送，提高网络的负载
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        //ChannelInitializer是一个特殊的类，他的目的是榜示使用者配置一个新的Channel,用于把许多自定义的处理类增加带pipline上来
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //在这里配置具体数据接收方法的处理
                            socketChannel.pipeline().addLast(new HandlerServerHello());
                        }
                    });

            //绑定服务器，该实力将提供有关的io操作结果或状态信息
            ChannelFuture channelFuture = bootstrap.bind().sync();
            System.out.println("在"+channelFuture.channel().localAddress()+"startup");

            //阻塞操作，closeFuture()开启一个channel的监听器，直到链路断开
            channelFuture.channel().closeFuture().sync();

        }finally {
            //关闭EventLoopGroup并释放所有资源，包括所有创建线程
            boss.shutdownGracefully().sync();
            work.shutdownGracefully().sync();
        }
    }

    public static void main(String[] args) throws Exception {
        new AppServerHello(18080).run();
    }
}
